package src.model.gameWorld;

import java.util.ArrayList;

import src.model.gameObject.GameObject;
import src.model.gameObject.GameObjectType;
import src.model.gameObject.ability.Ability;
import src.model.gameObject.ability.AbilityType;
import src.model.gameWorld.pathfinding.movement.*;

/**
 * <b>Overview</b><br>
 * <p>When the ActualMap is asked to place or move an object, the placement
 * needs to be validadet.  The MovementValidator encapsulates this idea,
 * allowing the ActualMap to remain unencumbered by GameObject details.</p>
 * <br><br>
 * <b>Responsibilites</b><br>
 * <p>validate GameObject/Position pairings</p>
 * <br><br>
 * <b>Collaborators</b>
 * <br><br>
 * <ul>
 * <li>ActualMap - Client</li>
 * <li>GameObject - Subcontractor</li>
 * <li>Position - Subcontractor</li>
 * <b>Implementor</b> - Brent<br>
 * <b>Tester</b> - Bruce<br>
 * 
 * @author Brent
 *
 */
public class MovementValidator implements Movement2D
{
	private ActualMap myMap;

	public MovementValidator(ActualMap map)
	{
		myMap = map;
	}

	public boolean validate(GameObject go, Position p)
	{
		ArrayList<GameObject> presentObjects = myMap.findObject(p);

		// if it is unmapped, then the positoin must be valid
		if (presentObjects == null) return true;

		for(GameObject current : presentObjects)
		{
			// if there's already a game object of that type there, we can't go there
			if (current.getType() == go.getType()) return false;

			// if the terrain or item there is impassable, we can't go there
			if (current.getType() == GameObjectType.TERRAIN || current.getType() == GameObjectType.ITEM)
			{
				boolean impassable = true;
				for(Ability a : current.getAbilities())
					if(a.abilityType() == AbilityType.PASSABLE) impassable = false;

				if(impassable) return false;
			}
		}

		return true;
	}

	public MovementCost getMovementCost(GameObject mover, Direction2D direction, Position pathfindingTerrain) throws IllegalTerrainException
	{
		if(!validate(mover, pathfindingTerrain))
		{
			throw new IllegalTerrainException();
		}
		return new DoubleMovementCost(direction.getVector().magnitude());
	}

	public MovementCost getMovementCost(GameObject mover, src.model.gameWorld.pathfinding.movement.Direction direction, Position pathfindingTerrain) throws IllegalTerrainException
	{
		if(direction instanceof Direction2D)
			return getMovementCost(mover, (Direction2D)direction, pathfindingTerrain);
		throw new IllegalTerrainException();
	}

	public boolean canMove(src.model.gameWorld.pathfinding.movement.Direction d)
	{
		return true;
	}
}